package org.geekbang.thinking.in.spring.bean.lifecycle;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author: wangsiqi
 * @date: 2021/10/31
 */
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware,
        EnvironmentAware, InitializingBean, SmartInitializingSingleton, DisposableBean {

    private String beanName;

    private BeanFactory beanFactory;

    private ClassLoader classLoader;

    private Environment environment;

    private final User user;

    private Integer number;

    private String desc;

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public Integer getNumber() {
        return number;
    }

    public UserHolder(User user) {
        this.user = user;
    }

    /**
     * 依赖于注解驱动
     */
    @PostConstruct
    public void initPostConstruct() {
        // postProcessBeforeInitialization: v3 -> initPostConstruct: v4
        this.desc = "the user holder version4";
        System.out.println("initPostConstruct(): " + desc) ;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // initPostConstruct: v4 -> InitializingBean#afterPropertiesSet v5
        this.desc = "the user holder version5";
        System.out.println("afterPropertiesSet(): " + desc);
    }

    // 自定义初始化方法
    public void init() {
        // InitializingBean#afterPropertiesSet v5 -> init v6
        this.desc = "the user holder version6";
        System.out.println("init(): " + desc);
    }

    @PreDestroy
    public void destroyPreDestroy() {
        // DestructionAwareBeanPostProcessor#postProcessBeforeDestruction v9 -> destroyPreDestroy v10
        this.desc = "the user holder version10";
        System.out.println("destroyPreDestroy(): " + desc);
    }

    @Override
    public void destroy() throws Exception {
        // destroyPreDestroy v10 -> DisposableBean#destroy v11
        this.desc = "the user holder version11";
        System.out.println("destroy(): " + desc);
    }

    // 自定义销毁方法
    public void doDestroy() {
        // DisposableBean#destroy v11 -> doDestroy v12
        this.desc = "the user holder version12";
        System.out.println("doDestroy(): " + desc);
    }

    @Override
    public String toString() {
        return "UserHolder{" +
                "beanName='" + beanName + '\'' +
                ", user=" + user +
                ", number=" + number +
                ", desc='" + desc + '\'' +
                '}';
    }

    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }


    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void afterSingletonsInstantiated() {
        // BeanPostProcessor#postProcessAfterInitialization: v7 -> SmartInitializingSingleton#afterSingletonsInstantiated: v8
        this.desc = "the user holder version8";
        System.out.println("afterSingletonsInstantiated(): " + desc);
    }


    @Override
    protected void finalize() throws Throwable {
        System.out.println("UserHolder is finalized...");
    }
}
